package com.SouthernWall_404.Age_Capitalism.common.Gui.Menu;

import com.SouthernWall_404.Age_Capitalism.common.API.Info.ClientStoreInfo;
import com.SouthernWall_404.Age_Capitalism.common.Gui.Slots.ModMerchantResultSlot;
import com.SouthernWall_404.Age_Capitalism.common.Init.ModMenuType;
import com.SouthernWall_404.Age_Capitalism.common.World.Entity.StoreBlockEntity;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.ClientSideMerchant;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.Merchant;
import net.minecraft.world.item.trading.MerchantOffer;
import net.minecraft.world.item.trading.MerchantOffers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ModMerchantMenu extends AbstractContainerMenu {

    private StoreBlockEntity storeBlockEntity;
    private ClientSideMerchant clientSideMerchant;
    private int windowId=0;


//    MerchantMenu
    protected static final int PAYMENT1_SLOT = 0;
    protected static final int PAYMENT2_SLOT = 1;
    protected static final int RESULT_SLOT = 2;
    private static final int INV_SLOT_START = 3;
    private static final int INV_SLOT_END = 30;
    private static final int USE_ROW_SLOT_START = 30;
    private static final int USE_ROW_SLOT_END = 39;
    private static final int SELLSLOT1_X = 136;
    private static final int SELLSLOT2_X = 162;
    private static final int BUYSLOT_X = 220;
    private static final int ROW_Y = 37;
    private final Merchant trader;
    private final MerchantContainer tradeContainer;
    private int merchantLevel;
    private boolean showProgressBar;
    private boolean canRestock;

    public ModMerchantMenu(int p_40033_, Inventory p_40034_) {

        this(p_40033_, p_40034_, new ClientSideMerchant(p_40034_.player));
    }


    public ModMerchantMenu(int i, Inventory inventory, Merchant merchant) {

        super(ModMenuType.MOD_MERCHANT_MENU.get(),i);

        this.trader = merchant;
        this.tradeContainer = new MerchantContainer(merchant);
        this.windowId=i;

        if(merchant instanceof StoreBlockEntity storeBlock)
        {
            this.storeBlockEntity=(StoreBlockEntity) merchant;
        }







        this.addSlot(new Slot(this.tradeContainer, 0, 136, 37));
        this.addSlot(new Slot(this.tradeContainer, 1, 162, 37));
        this.addSlot(new ModMerchantResultSlot(inventory.player, merchant, this.tradeContainer, 2, 220, 37,this.storeBlockEntity));

        for(int $$3 = 0; $$3 < 3; ++$$3) {
            for(int $$4 = 0; $$4 < 9; ++$$4) {
                this.addSlot(new Slot(inventory, $$4 + $$3 * 9 + 9, 108 + $$4 * 18, 84 + $$3 * 18));
            }
        }

        for(int $$5 = 0; $$5 < 9; ++$$5) {
            this.addSlot(new Slot(inventory, $$5, 108 + $$5 * 18, 142));
        }

    }
    public void setShowProgressBar(boolean p_40049_) {
        this.showProgressBar = p_40049_;
    }

    public void slotsChanged(Container p_40040_) {
        this.tradeContainer.updateSellItem();
        super.slotsChanged(p_40040_);
    }

    public boolean stillValid(Player p_40042_) {
        return this.trader.getTradingPlayer() == p_40042_;
    }

    public int getTraderXp() {
        return this.trader.getVillagerXp();
    }

    public int getFutureTraderXp() {
        return this.tradeContainer.getFutureXp();
    }

    public void setXp(int p_40067_) {
        this.trader.overrideXp(p_40067_);
    }

    public int getTraderLevel() {
        return this.merchantLevel;
    }

    public void setMerchantLevel(int p_40070_) {
        this.merchantLevel = p_40070_;
    }

    public void setCanRestock(boolean p_40059_) {
        this.canRestock = p_40059_;
    }

    public boolean canRestock() {
        return this.canRestock;
    }

    public boolean canTakeItemForPickAll(ItemStack p_40044_, Slot p_40045_) {
        return false;
    }

    @Override
    public ItemStack quickMoveStack(Player player, int index) {

         if(this.storeBlockEntity==null)
        {
            Map<Integer, StoreBlockEntity> entityMap =ClientStoreInfo.entityMap;
            this.storeBlockEntity= entityMap.get(this.windowId);
        }

        ItemStack output = ItemStack.EMPTY;//目标输出
        Slot currentSlot = (Slot)this.slots.get(index);//获取当前位置
        if (currentSlot != null && currentSlot.hasItem()) {
            ItemStack currentSlotItem = currentSlot.getItem();
            output = currentSlotItem.copy();
            if (index == 2) {//如果当前是输出结果栏
                Slot resultSlot = this.slots.get(RESULT_SLOT);
                if (resultSlot != null && resultSlot.hasItem()&&!this.tradeContainer.isEmpty()) {
                    // 触发结果槽的onTake执行交易逻辑



                    int maxTrades = 0;
                    if(this.tradeContainer!=null)
                    {
                        maxTrades=calculateMaxTrades(player, tradeContainer.getActiveOffer(), resultSlot.getItem());
                    }

                    for(int j=0;j<maxTrades;j++)
                    {
                        if (!this.moveItemStackTo(currentSlotItem.copy(), 3, 39, true)) {
                            return ItemStack.EMPTY;
                        }
                        resultSlot.onTake(player, resultSlot.getItem());

                    }
//                    resultSlot.onTake(player, resultSlot.getItem());

                    this.playTradeSound();
                }
            } else if (index != 0 && index != 1) {
                if (index >= 3 && index < 30) {
                    if (!this.moveItemStackTo(currentSlotItem, 30, 39, false)) {
                        return ItemStack.EMPTY;
                    }
                } else if (index >= 30 && index < 39 && !this.moveItemStackTo(currentSlotItem, 3, 30, false)) {
                    return ItemStack.EMPTY;
                }
            } else if (!this.moveItemStackTo(currentSlotItem, 3, 39, false)) {
                return ItemStack.EMPTY;
            }

            if (currentSlotItem.isEmpty()) {
                currentSlot.setByPlayer(ItemStack.EMPTY);
            } else {
                currentSlot.setChanged();
            }

            if (currentSlotItem.getCount() == output.getCount()) {
                return ItemStack.EMPTY;
            }

            currentSlot.onTake(player, currentSlotItem);
        }
        return output;
    }

    private int calculateMaxTrades(Player player, MerchantOffer offer, ItemStack resultStack) {
        // a. 支付槽物品数量限制
        ItemStack payment1 = this.slots.get(0).getItem();
        ItemStack payment2 = this.slots.get(1).getItem();

        int maxFromPayment1 = payment1.getCount() / offer.getCostA().getCount();
        int maxFromPayment2 = offer.getCostB().isEmpty() ? Integer.MAX_VALUE :
                payment2.getCount() / offer.getCostB().getCount();

        // b. 商店库存结果物品限制
        int maxFromStock = 0;
        NonNullList<ItemStack> chest = this.storeBlockEntity.getContainer();
        for (ItemStack stack : chest) {
            if (ItemStack.isSameItemSameTags(stack, offer.getResult())) {
                maxFromStock += stack.getCount();
            }
        }
        maxFromStock /= offer.getResult().getCount();

        // c. 玩家背包空间限制
        int maxFromPlayer = calculatePlayerSpace(player, offer.getResult());

        // 取最小值
        return Math.min(
                Math.min(maxFromPayment1, maxFromPayment2),
                Math.min(maxFromStock, maxFromPlayer)
        );
    }

    // 计算玩家背包可容纳数量
    private int calculatePlayerSpace(Player player, ItemStack result) {
        int space = 0;
        for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
            ItemStack stack = player.getInventory().getItem(i);
            if (stack.isEmpty()) {
                space += result.getMaxStackSize();
            } else if (ItemStack.isSameItemSameTags(stack, result)) {
                space += result.getMaxStackSize() - stack.getCount();
            }
        }
        return space / result.getCount();
    }


    public void setSelectionHint(int i) {
        this.tradeContainer.setSelectionHint(i);
    }


    private void playTradeSound() {
        if (!this.trader.isClientSide()) {
            Entity $$0 = (Entity)this.trader;
            $$0.level().playLocalSound($$0.getX(), $$0.getY(), $$0.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false);
        }

    }

    public void removed(Player p_40051_) {
        super.removed(p_40051_);
        this.trader.setTradingPlayer((Player)null);
        if (!this.trader.isClientSide()) {
            if (!p_40051_.isAlive() || p_40051_ instanceof ServerPlayer && ((ServerPlayer)p_40051_).hasDisconnected()) {
                ItemStack $$1 = this.tradeContainer.removeItemNoUpdate(0);
                if (!$$1.isEmpty()) {
                    p_40051_.drop($$1, false);
                }

                $$1 = this.tradeContainer.removeItemNoUpdate(1);
                if (!$$1.isEmpty()) {
                    p_40051_.drop($$1, false);
                }
            } else if (p_40051_ instanceof ServerPlayer) {
                p_40051_.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(0));
                p_40051_.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(1));
            }

        }
    }


    public void tryMoveItems(int p_40073_) {
        if (p_40073_ >= 0 && this.getOffers().size() > p_40073_) {
            ItemStack $$1 = this.tradeContainer.getItem(0);
            if (!$$1.isEmpty()) {
                if (!this.moveItemStackTo($$1, 3, 39, true)) {
                    return;
                }

                this.tradeContainer.setItem(0, $$1);
            }

            ItemStack $$2 = this.tradeContainer.getItem(1);
            if (!$$2.isEmpty()) {
                if (!this.moveItemStackTo($$2, 3, 39, true)) {
                    return;
                }

                this.tradeContainer.setItem(1, $$2);
            }

            if (this.tradeContainer.getItem(0).isEmpty() && this.tradeContainer.getItem(1).isEmpty()) {
                ItemStack $$3 = ((MerchantOffer)this.getOffers().get(p_40073_)).getCostA();
                this.moveFromInventoryToPaymentSlot(0, $$3);
                ItemStack $$4 = ((MerchantOffer)this.getOffers().get(p_40073_)).getCostB();

                this.moveFromInventoryToPaymentSlot(1, $$4);
            }

        }
    }

    private void moveFromInventoryToPaymentSlot(int p_40061_, ItemStack p_40062_) {
        if (!p_40062_.isEmpty()) {
            for(int $$2 = 3; $$2 < 39; ++$$2) {
                ItemStack $$3 = ((Slot)this.slots.get($$2)).getItem();
                if (!$$3.isEmpty() && ItemStack.isSameItemSameTags(p_40062_, $$3)) {
                    ItemStack $$4 = this.tradeContainer.getItem(p_40061_);
                    int $$5 = $$4.isEmpty() ? 0 : $$4.getCount();
                    int $$6 = Math.min(p_40062_.getMaxStackSize() - $$5, $$3.getCount());
                    ItemStack $$7 = $$3.copy();
                    int $$8 = $$5 + $$6;
                    $$3.shrink($$6);
                    $$7.setCount($$8);
                    this.tradeContainer.setItem(p_40061_, $$7);
                    if ($$8 >= p_40062_.getMaxStackSize()) {
                        break;
                    }
                }
            }
        }

    }

    public void setOffers(MerchantOffers p_40047_) {
        this.trader.overrideOffers(p_40047_);
    }

    public MerchantOffers getOffers() {
        return this.trader.getOffers();
    }

    public boolean showProgressBar() {
        return this.showProgressBar;
    }
}
